﻿// Copyright (c) 2012 - 2021 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2021-03-19 version 4.0.0 Jared Zheng <jaredz at outlook dot com>

#include "stdafx.h"
#include "ServerLoader.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CMainHandler
CMainHandler::CMainHandler(void)
: m_uStatus(SERVERS_NONE)
, m_uLoad(0)
{
    MM_SAFE::Set(m_pHandler, 0, sizeof(CCommonHandler*) * COMMONR_MAX);
}

CMainHandler::~CMainHandler(void)
{
    Exit();
}

bool CMainHandler::Init(void)
{
    if (m_uStatus == SERVERS_NONE)
    {
        if (InitHandler() == false)
        {
            LOG_ERROR(GServerLoaderInst->m_FileLog, TF("服务初始化失败!"));
            ExitHandler();
            return false;
        }
        m_uStatus = SERVERS_INIT;
        LOG_INFO(GServerLoaderInst->m_FileLog, TF("服务初始化完成!"));
    }
    return (m_uStatus == SERVERS_INIT);
}

void CMainHandler::Exit(void)
{
    if (m_uStatus != SERVERS_NONE)
    {
        Stop();
        ExitHandler();
        LOG_INFO(GServerLoaderInst->m_FileLog, TF("服务结束完成!"));
    }
}

bool CMainHandler::Start(void)
{
    if (m_uStatus == SERVERS_INIT)
    {
        if (StartHandler() == false)
        {
            LOG_ERROR(GServerLoaderInst->m_FileLog, TF("服务开启失败!"));
            StopHandler();
            return false;
        }
        m_uStatus = SERVERS_RUN;

        CEventQueue::CreateTickEvent(CServerConfig::TIMED_UPDATE_ID, GServerLoaderInst->m_Config.GetUpdateTick() * TIMET_XS2XS, *this);
        LOG_INFO(GServerLoaderInst->m_FileLog, TF("服务开启完成!"));
    }
    return (m_uStatus == SERVERS_RUN);
}

void CMainHandler::Stop(void)
{
    if (m_uStatus == SERVERS_RUN)
    {
        CEventQueue::DestroyTickEvent(CServerConfig::TIMED_UPDATE_ID);

        StopHandler();

        m_uLoad   = 0;
        m_uStatus = SERVERS_INIT;
        LOG_INFO(GServerLoaderInst->m_FileLog, TF("服务停止完成!"));
    }
}

UInt CMainHandler::OnHandle(uintptr_t, uintptr_t, ULLong)
{
    return RET_FAIL;
}

UInt CMainHandler::OnHandle(uintptr_t, CEventBase&, ULLong)
{
    return RET_FAIL;
}

UInt CMainHandler::OnHandle(uintptr_t, CStream&, ULLong)
{
    return RET_FAIL;
}

UInt CMainHandler::OnHandle(uintptr_t utEvent, UInt uCount)
{
    if (utEvent == CServerConfig::TIMED_UPDATE_ID)
    {
        for (UInt i = 0; i < COMMONR_MAX; ++i)
        {
            if (m_pHandler[i] != nullptr)
            {
                m_pHandler[i]->OnHandle(utEvent, uCount);
            }
        }
        GServerLoaderInst->m_FileLog.Flush();
    }
    return RET_OKAY;
}

bool CMainHandler::InitHandler(void)
{
    for (UInt i = 0; i < COMMONR_MAX; ++i)
    {
        CCommonHandler* pHandler = nullptr;

        const SERVER_CONFIG& sc = GServerLoaderInst->m_Config.GetServerConfig(i);
        switch (sc.usType)
        {
        case COMMONT_MASTER:
        case COMMONT_SLAVE:
        case COMMONT_NODE:
            {
                pHandler = MNEW CCommonHandler;
            }
            break;
        default:
            {
                continue;
            }
        }
        if ((pHandler == nullptr) || (pHandler->Init(i) == false))
        {
            LOGV_ERROR(GServerLoaderInst->m_FileLog, TF("初始化服务Type=%d, Rank=%d, Name=%s失败"), sc.usType, i, sc.strName.GetBuffer());
            if (pHandler != nullptr)
            {
                pHandler->Exit();
                MDELETE pHandler;
            }
            return false;
        }
        m_pHandler[i] = pHandler;
        LOGV_INFO(GServerLoaderInst->m_FileLog, TF("初始化服务Type=%d, Rank=%d, Name=%s完成"), sc.usType, i, sc.strName.GetBuffer());
    }
    return true;
}

void CMainHandler::ExitHandler(void)
{
    for (UInt i = 0; i < COMMONR_MAX; ++i)
    {
        if (m_pHandler[i] != nullptr)
        {
            m_pHandler[i]->Exit();

            MDELETE m_pHandler[i];
            m_pHandler[i] = nullptr;

            const SERVER_CONFIG& sc = GServerLoaderInst->m_Config.GetServerConfig(i);
            LOGV_INFO(GServerLoaderInst->m_FileLog, TF("结束服务Type=%d, Rank=%d, Name=%s完成"), sc.usType, i, sc.strName.GetBuffer());
        }
    }
}

bool CMainHandler::StartHandler(void)
{
    for (UInt i = 0; i < COMMONR_MAX; ++i)
    {
        const SERVER_CONFIG& sc = GServerLoaderInst->m_Config.GetServerConfig(i);
        if (m_pHandler[i] != nullptr)
        {
            if (m_pHandler[i]->Start() == false)
            {
                LOGV_ERROR(GServerLoaderInst->m_FileLog, TF("开启服务Type=%d, Rank=%d, Name=%s失败"), sc.usType, i, sc.strName.GetBuffer());
                return false;
            }
            LOGV_INFO(GServerLoaderInst->m_FileLog, TF("开启服务Type=%d, Rank=%d, Name=%s完成"), sc.usType, i, sc.strName.GetBuffer());
        }
    }
    return true;
}

void CMainHandler::StopHandler(void)
{
    UInt uRank = 0;
    for (UInt i = COMMONR_MAX; i > COMMONR_MASTER; --i)
    {
        uRank = i - COMMONR_MIN;
        if (m_pHandler[uRank] != nullptr)
        {
            m_pHandler[uRank]->Stop();
        }
    }
    CPlatform::SleepEx(CServerConfig::TIMED_WAIT_UNLINK);

    for (UInt i = COMMONR_MAX; i > COMMONR_MASTER; --i)
    {   
        uRank = i - COMMONR_MIN;
        if (m_pHandler[uRank] != nullptr)
        {
            m_pHandler[uRank]->Stop(false);

            const SERVER_CONFIG& sc = GServerLoaderInst->m_Config.GetServerConfig(uRank);
            LOGV_INFO(GServerLoaderInst->m_FileLog, TF("停止服务Type=%d, Rank=%d, Name=%s完成"), sc.usType, uRank, sc.strName.GetBuffer());
        }
    }
}

